﻿using SqlSugar;
using System;

namespace ALEXBlog.Repository.Sugar
{
    public class DbContext
    {
        private static string connectionString = BaseDbConfig.ConnectionString;
        public static DbType dbType;
        public SqlSugarClient dbClient;

        public DbContext()
        {
            if (string.IsNullOrEmpty(connectionString))
                throw new ArgumentNullException("数据库连接字符串为空");
            dbClient = new SqlSugarClient(new ConnectionConfig()
            {
                ConnectionString = connectionString,
                DbType = dbType,
                IsAutoCloseConnection = true,
                IsShardSameThread = true,
                InitKeyType = InitKeyType.Attribute,
                ConfigureExternalServices = new ConfigureExternalServices()
                {
                    //DataInfoCacheService = new HttpRuntimeCache()
                },
                MoreSettings = new ConnMoreSettings()
                {
                    //IsWithNoLockQuery = true,
                    IsAutoRemoveDataCache = true
                }
            });
        }
        public DbContext(bool isAtuoCloseConnection)
        {
            if (string.IsNullOrEmpty(connectionString))
                throw new ArgumentNullException("数据库连接字符串为空");
            dbClient = new SqlSugarClient(new ConnectionConfig()
            {
                ConnectionString = connectionString,
                DbType = dbType,
                IsAutoCloseConnection = isAtuoCloseConnection,
                IsShardSameThread = true,
                InitKeyType = InitKeyType.Attribute,
                ConfigureExternalServices = new ConfigureExternalServices()
                {
                    //DataInfoCacheService = new HttpRuntimeCache()
                },
                MoreSettings = new ConnMoreSettings()
                {
                    //IsWithNoLockQuery = true,
                    IsAutoRemoveDataCache = true
                }
            });
        }
        public DbContext(ConnectionConfig connectionConfig)
        {
            dbClient = new SqlSugarClient(connectionConfig);
        }

        #region 实体对象
        /// <summary>
        /// 获取DB对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public SimpleClient<T> GetEntityDB<T>() where T : class, new()
        {
            return new SimpleClient<T>(dbClient);
        }

        /// <summary>
        /// 获取DB对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public SimpleClient<T> GetEntityDB<T>(SqlSugarClient client) where T : class, new()
        {
            return new SimpleClient<T>(client);
        }
        #endregion

        #region 根据数据库表产生实体类
        /// <summary>
        /// 根据数据库产生实体
        /// </summary>
        /// <param name="path">实体存放路径</param>
        /// <summary>
        /// 功能描述:根据数据库表生产实体类
        /// </summary>       
        /// <param name="strPath">实体类存放路径</param>
        public void CreateClassFileByDBTalbe(string strPath)
        {
            CreateClassFileByDBTalbe(strPath, "Km.PosZC");
        }
        /// <summary>
        /// 功能描述:根据数据库表生产实体类
        /// </summary>
        /// <param name="strPath">实体类存放路径</param>
        /// <param name="strNameSpace">命名空间</param>
        public void CreateClassFileByDBTalbe(string strPath, string strNameSpace)
        {
            CreateClassFileByDBTalbe(strPath, strNameSpace, null);
        }

        /// <summary>
        /// 功能描述:根据数据库表生产实体类
        /// </summary>
        /// <param name="strPath">实体类存放路径</param>
        /// <param name="strNameSpace">命名空间</param>
        /// <param name="lstTableNames">生产指定的表</param>
        public void CreateClassFileByDBTalbe(
            string strPath,
            string strNameSpace,
            string[] lstTableNames)
        {
            CreateClassFileByDBTalbe(strPath, strNameSpace, lstTableNames, string.Empty);
        }

        /// <summary>
        /// 功能描述:根据数据库表生产实体类
        /// </summary>
        /// <param name="strPath">实体类存放路径</param>
        /// <param name="strNameSpace">命名空间</param>
        /// <param name="lstTableNames">生产指定的表</param>
        /// <param name="strInterface">实现接口</param>
        public void CreateClassFileByDBTalbe(
          string strPath,
          string strNameSpace,
          string[] lstTableNames,
          string strInterface,
          bool blnSerializable = false)
        {
            if (lstTableNames != null && lstTableNames.Length > 0)
            {
                dbClient.DbFirst.Where(lstTableNames).IsCreateDefaultValue().IsCreateAttribute()
                    .SettingClassTemplate(p => p = @"
                    {using}
                    
                    namespace {Namespace}
                    {
                        {ClassDescription}{SugarTable}" + (blnSerializable ? "[Serializable]" : "") + @"
                        public partial class {ClassName}" + (string.IsNullOrEmpty(strInterface) ? "" : (" : " + strInterface)) + @"
                        {
                            public {ClassName}()
                            {
                             {Constructor}
                            }
                           {PropertyName}
                        }
                    }
                    ").SettingPropertyTemplate(p => p = @"
                    {SugarColumn}
                    public {PropertyType} {PropertyName}
                    {
                        get
                        {
                            return _{PropertyName};
                        }
                        set
                        {
                            if(_{PropertyName}!=value)
                            {
                                base.SetValueCall(" + "\"{PropertyName}\",_{PropertyName}" + @");
                            }
                            _{PropertyName}=value;
                        }
                    }").SettingPropertyDescriptionTemplate(p => p = "          private {PropertyType} _{PropertyName};\r\n" + p)
                    .SettingConstructorTemplate(p => p = "              this._{PropertyName} ={DefaultValue};")
                    .CreateClassFile(strPath, strNameSpace);
            }
            else
            {
                dbClient.DbFirst.IsCreateAttribute().IsCreateDefaultValue()
                    .SettingClassTemplate(p => p = @"
                   {using}
                   
                   namespace {Namespace}
                   {
                       {ClassDescription}{SugarTable}" + (blnSerializable ? "[Serializable]" : "") + @"
                       public partial class {ClassName}" + (string.IsNullOrEmpty(strInterface) ? "" : (" : " + strInterface)) + @"
                       {
                           public {ClassName}()
                           {
                   {Constructor}
                           }
                   {PropertyName}
                       }
                   }
                   ").SettingPropertyTemplate(p => p = @"
                   {SugarColumn}
                   public {PropertyType} {PropertyName}
                   {
                       get
                       {
                           return _{PropertyName};
                       }
                       set
                       {
                           if(_{PropertyName}!=value)
                           {
                               base.SetValueCall(" + "\"{PropertyName}\",_{PropertyName}" + @");
                           }
                           _{PropertyName}=value;
                       }
                   }")
                    .SettingPropertyDescriptionTemplate(p => p = "          private {PropertyType} _{PropertyName};\r\n" + p)
                    .SettingConstructorTemplate(p => p = "              this._{PropertyName} ={DefaultValue};")
                    .CreateClassFile(strPath, strNameSpace);
            }
        }
        #endregion

        #region 根据实体类产生数据表
        /// <summary>
        /// 根据实体类生成数据表
        /// </summary>
        /// <param name="blnBackupTable">是否备份表</param>
        /// <param name="lstEntitys">指定的实体?</param>
        public void CreateTableByEntity<T>(bool blnBackupTable, params T[] lstEntitys) where T : class, new()
        {
            Type[] lstTypes = null;
            if (lstEntitys != null)
            {
                lstTypes = new Type[lstEntitys.Length];
                for (int i = 0; i < lstTypes.Length; i++)
                {
                    T t = lstEntitys[i];
                    lstTypes[i] = typeof(T);
                }
            }
            CreateTableByEntity(blnBackupTable, lstTypes);
        }
        /// <summary>
        /// 根据实体类生成数据表
        /// </summary>
        /// <param name="blnBackupTable">是否备份表</param>
        /// <param name="lstEntitys">指定的实体?</param>
        public void CreateTableByEntity(bool blnBackupTable, params Type[] lstEntitys)
        {
            if (blnBackupTable)
            {
                dbClient.CodeFirst.BackupTable().InitTables(lstEntitys);
            }
            else
            {
                dbClient.CodeFirst.InitTables(lstEntitys);
            }
        }
        #endregion

        #region 静态方法

        /// <summary>
        /// New 一个 DbContext
        /// </summary>
        /// <param name="blnIsAutoCloseConnection">是否自动关闭连接</param>
        /// <returns></returns>
        public static DbContext GetDbContext(bool blnIsAutoCloseConnection = true)
        {
            return new DbContext(blnIsAutoCloseConnection);
        }

        /// <summary>
        /// 初始化参数
        /// </summary>
        /// <param name="strConnectionString">连接串</param>
        /// <param name="enmDbType">数据库类型</param>
        public static void Init(string strConnectionString, DbType enmDbType = SqlSugar.DbType.MySql)
        {
            connectionString = strConnectionString;
            dbType = enmDbType;
        }
        /// <summary>
        /// 创建一个ConnectionConfig
        /// </summary>
        /// <param name="blnIsAutoCloseConnection">是否自动关闭连接</param>
        /// <param name="blnIsShardSameThread">是否跨类事务</param>
        /// <returns></returns>
        public static ConnectionConfig GetConnectionConfig(bool blnIsAutoCloseConnection = true, bool blnIsShardSameThread = false)
        {
            return new ConnectionConfig()
            {
                ConnectionString = connectionString,
                DbType = dbType,
                IsAutoCloseConnection = blnIsAutoCloseConnection,
                IsShardSameThread = blnIsShardSameThread,
                ConfigureExternalServices = new ConfigureExternalServices()
                {
                    //DataInfoCacheService = new HttpRuntimeCache()
                },
                MoreSettings = new ConnMoreSettings()
                {
                    //IsWithNoLockQuery = true,
                    IsAutoRemoveDataCache = true
                }
            };
        }
        /// <summary>
        /// 获取一个自定义Db实例
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static SqlSugarClient GetCustomDb(ConnectionConfig config)
        {
            return new SqlSugarClient(config);
        }
        /// <summary>
        /// 获取一个自定义的数据库处理对象
        /// </summary>
        /// <param name="sugarClient">sugarClient</param>
        /// <returns>返回值</returns>
        public static SimpleClient<T> GetCustomEntityDb<T>(SqlSugarClient sqlSugarClient) where T : class, new()
        {
            return new SimpleClient<T>(sqlSugarClient);
        }

        /// <summary>
        /// 获取一个自定义的数据库处理对象
        /// </summary>
        /// <param name="sugarClient">sugarClient</param>
        /// <returns>返回值</returns>
        public static SimpleClient<T> GetCustomEntityDb<T>(ConnectionConfig config) where T : class, new()
        {
            return new SimpleClient<T>(new SqlSugarClient(config));
        }
        #endregion
    }
}
